package otSpaces.client.demo;

import java.io.IOException;
import java.net.PasswordAuthentication;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.Properties;
import java.util.Random;
import java.util.logging.Logger;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;

import otSpaces.OtSpaceFunctions;
import otSpaces.client.OtSpaceClient;
import otSpaces.util.TreeModel;
import otSpaces.util.TreeModel.Impl.Selected;

import com.sun.sgs.client.ClientChannel;
import com.sun.sgs.client.ClientChannelListener;
import com.sun.sgs.client.simple.SimpleClient;
import com.sun.sgs.client.simple.SimpleClientListener;

public class DemoTreeClient extends JFrame implements SimpleClientListener,
		Selected {

	public static final Logger LOG = Logger.getLogger(DemoTreeClient.class
			.getName());

	private static final long serialVersionUID = 1L;

	public static final long STARTUP_TIME = System.currentTimeMillis();

	public static void main(String... args) {

		final Object result = JOptionPane.showInputDialog(null,
				"Connect to server", "Ready?", JOptionPane.PLAIN_MESSAGE, null,
				null, "localhost:62964");

		if (result == null) {
			System.exit(0);
		}

		final DemoTreeClient treeClient = new DemoTreeClient();

		final Properties properties = new Properties(System.getProperties());

		properties
				.setProperty(
						"port",
						result.toString().substring(
								result.toString().indexOf(':') + 1));
		properties.setProperty("host",
				result.toString().substring(0, result.toString().indexOf(':')));

		try {
			treeClient._simpleClient.login(properties);
			try {
				synchronized (treeClient) {
					treeClient.wait(10000L);
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static String name() {
		return "TreeClient @ " + STARTUP_TIME;
	}

	public final TreeModel _root;
	private final JScrollPane _scrollPane = new JScrollPane();

	public final SimpleClient _simpleClient = new SimpleClient(this);

	public DemoTreeClient() {
		super(name());

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		_root = new TreeModel.Impl(name(), this);

		_scrollPane.setViewportView(_root.getJTree());

		add(_scrollPane);

		setSize(640, 480);

		setVisible(true);

	}

	@Override
	public void disconnected(boolean graceful, String reason) {
		LOG.info("Grace" + (graceful ? "fully" : "lessly") + " because ["
				+ reason + "]");
		System.exit(0);
	}

	@Override
	public PasswordAuthentication getPasswordAuthentication() {
		synchronized (this) {
			return new PasswordAuthentication(getClass().getName()
					+ (new Random().nextLong()), new char[0]);
		}
	}

	@Override
	public ClientChannelListener joinedChannel(ClientChannel channel) {

		// == DEMO ==
		// check if it's a ToSpace
		if (OtSpaceFunctions.isOtTopicSpaceName(channel.getName())) {

			final OtSpaceClient clientSpace = new OtSpaceClient(channel);

			// add a tree node for this client space
			final TreeModel space = _root.branch("+Space : ["
					+ clientSpace._topicSpaceName + "]", false);
			repaint();

			// == DEMO ==
			// OtSpaceClient.Listener
			final OtSpaceClient.Listener listener = new OtSpaceClient.Listener() {

				@Override
				public ClientChannelListener joinedTopic(String topicSpaceName,
						ClientChannel channel) {

					final TreeModel topic = space.branch(
							"+Topic : [" + channel.getName() + "]", true);

					topic.getMappings().put("Channel", channel);

					repaint();

					return new ClientChannelListener() {

						int c = 0;

						@Override
						public void leftChannel(ClientChannel channel) {
							topic.setName("-" + topic.getName().substring(1));
						}

						@Override
						public void receivedMessage(ClientChannel channel,
								ByteBuffer message) {
							topic.branch("Message " + (c++) + " sent at "
									+ new Date(message.getLong()), false);
							repaint();
						}
					};
				}

				@Override
				public void leftTopicSpace(String topicSpaceName) {
					space.setName("-" + space.getName().substring(1));
				}
			};

			// == DEMO ==
			// now return it all wrapped
			return clientSpace.wrap(listener);
		} else {
			// TODO Auto-generated method stub
			throw new UnsupportedOperationException(
					"TODO Auto-generated method stub");
		}
	}

	@Override
	public void loggedIn() {
		LOG.info(" ");
	}

	@Override
	public void loginFailed(String reason) {
		LOG.info("Because [" + reason + "]");
		System.exit(0);
	}

	@Override
	public void receivedMessage(ByteBuffer message) {
		// TODO Auto-generated method stub
		throw new UnsupportedOperationException(
				"TODO Auto-generated method stub");
	}

	@Override
	public void reconnected() {
		LOG.info(" ");
	}

	@Override
	public void reconnecting() {
		LOG.info(" ");
	}

	@Override
	public void selected(TreeModel node) {
		LOG.info("Sending upstream ...");

		final ClientChannel channel = (ClientChannel) node.getMappings().get(
				"Channel");

		node.branch("Upstream", false);

		final ByteBuffer data = ByteBuffer.allocate(8);

		data.putLong(System.currentTimeMillis());

		data.flip();

		try {
			channel.send(data);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
